package com.bjfu.demo.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.bjfu.demo.constant.BaseConstant;
import com.bjfu.demo.dao.DataMapper;
import com.bjfu.demo.dao.SearchDto;
import com.bjfu.demo.dao.SiteDataMapper;
import com.bjfu.demo.dao.ext.CustomerMapper;
import com.bjfu.demo.dto.AllCityVo;
import com.bjfu.demo.dto.CityDayEvaluationVo;
import com.bjfu.demo.dto.CityHourEvaluationVo;
import com.bjfu.demo.dto.CityLast7daysVo;
import com.bjfu.demo.dto.CityMonthEvaluationVo;
import com.bjfu.demo.dto.CityQuarterlyDataVo;
import com.bjfu.demo.dto.HistoricalAirdata24HourVo;
import com.bjfu.demo.dto.HistoricalAirdata7DayVo;
import com.bjfu.demo.dto.LatestNewDataVo;
import com.bjfu.demo.dto.RankingVo;
import com.bjfu.demo.dto.SearchVo;
import com.bjfu.demo.entity.Data;
import com.bjfu.demo.entity.DataExample;
import com.bjfu.demo.entity.SiteData;
import com.bjfu.demo.entity.SiteDataExample;
import com.bjfu.demo.entity.SiteDataExample.Criteria;
import com.bjfu.demo.metric.TrackTime;
import com.bjfu.demo.utils.AvgUtils;
import com.bjfu.demo.utils.JsonUtils;
import com.bjfu.demo.utils.MaxUtils;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;

/**
 * Created on 2021-04-29
 */
@Service
public class PyService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private SiteDataMapper siteDataMapper;

    @Autowired
    private DataMapper dataMapper;

    private List<SiteData> siteDataCache;

    @PostConstruct
    private void init() {
        siteDataCache = siteDataMapper.selectByExample(new SiteDataExample());
    }

    @TrackTime
    public List getAllData() {

        // 获取所有站点
        List<SiteData> siteData = siteDataMapper.selectByExample(new SiteDataExample());

        // 构建站点和最新数据记录
        List<LatestNewDataVo> collect =
                siteData.stream().map(x -> buildLatestNewDataVo(x)).collect(Collectors.toList());

        DataExample dataExample = new DataExample();
        DataExample.Criteria criteria = dataExample.createCriteria();
        // 时间
        criteria.andCollecttimeGreaterThanOrEqualTo(DateUtil.beginOfDay(new Date()));
        List<Data> data = dataMapper.selectByExample(dataExample);
        Map<String, List<Data>> dataMap =
                data.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        for (LatestNewDataVo latestNewDataVo : collect) {

            List<Data> dataList = dataMap.get(latestNewDataVo.getSitecode().toLowerCase());

            if (CollectionUtils.isEmpty(dataList)) {
                dataList = new ArrayList<>();
            }

            List<String> col1s = dataList.stream().map(x -> x.getCol1()).collect(Collectors.toList());
            col1s.add(latestNewDataVo.getCol1());
            latestNewDataVo.setMaxcol1(MaxUtils.getMaxFromString(col1s));
        }

        return collect;
    }

    public List currentcity(String city) {
        SiteDataExample siteDataExample = new SiteDataExample();
        Criteria criteria = siteDataExample.createCriteria();
        // 添加city条件
        criteria.andDistrictEqualTo(city);
        List<SiteData> siteData = siteDataMapper.selectByExample(siteDataExample);
        List<LatestNewDataVo> collect =
                siteData.stream().map(x -> buildLatestNewDataVo(x)).collect(Collectors.toList());

        // 查询某站点今日的最大值
        DataExample dataExample = new DataExample();
        DataExample.Criteria dataExampleCriteria = dataExample.createCriteria();
        // 时间
        dataExampleCriteria.andCollecttimeEqualTo(DateUtil.beginOfDay(new Date()));
        List<Data> data = dataMapper.selectByExample(dataExample);
        Map<String, List<Data>> dataMap =
                data.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        for (LatestNewDataVo latestNewDataVo : collect) {

            List<Data> dataList = dataMap.get(latestNewDataVo.getSitecode().toLowerCase());

            if (CollectionUtils.isEmpty(dataList)) {
                dataList = new ArrayList<>();
            }

            List<String> col1s = dataList.stream().map(x -> x.getCol1()).collect(Collectors.toList());
            col1s.add(latestNewDataVo.getCol1());

            latestNewDataVo.setMaxcol1(MaxUtils.getMaxFromString(col1s));

            // 设置城市
            latestNewDataVo.setCity(latestNewDataVo.getDistrict());
        }

        return collect;
    }

    /**
     * 构建站点和最新的一条数据
     */
    private LatestNewDataVo buildLatestNewDataVo(SiteData siteData) {

        Data data = customerMapper.selectLatestNewData(siteData.getSitecode().toLowerCase());

        LatestNewDataVo latestNewDataVo = new LatestNewDataVo();
        if (null != data) {
            BeanUtils.copyProperties(data, latestNewDataVo);
        }
        BeanUtils.copyProperties(siteData, latestNewDataVo);

        return latestNewDataVo;
    }

    /**
     * 接口4 根据城市、清新等级名称、时间查询相应站点
     */
    public List search(SearchDto searchDto) {
        List<SearchVo> searchVos = new ArrayList<>();

        // 查询站点
        SiteDataExample siteDataExample = new SiteDataExample();
        Criteria criteria = siteDataExample.createCriteria();
        criteria.andDistrictEqualTo(searchDto.getCity());
        List<SiteData> siteData = siteDataMapper.selectByExample(siteDataExample);
        Map<String, List<SiteData>> SiteDataMap =
                siteData.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        // 根据条件查询数据
        DataExample dataExample = new DataExample();
        DataExample.Criteria criteria1 = dataExample.createCriteria();
        // 时间
        DateTime startTime = DateUtil.parse(searchDto.getSearchDayTime());
        DateTime endTime = DateUtil.offsetDay(startTime, 1);
        criteria1.andCollecttimeBetween(startTime, endTime);
        // 清新度
        criteria1.andAirlevelnameEqualTo(searchDto.getAIRLEVELNAME());
        List<Data> data = dataMapper.selectByExample(dataExample);
        Map<String, List<Data>> dataMap =
                data.stream().collect(Collectors.groupingBy(Data::getSitecode));

        Set<Entry<String, List<Data>>> entries = dataMap.entrySet();
        for (Entry<String, List<Data>> entry : entries) {

            String key = entry.getKey();
            Data data1 = entry.getValue().get(0);

            List<SiteData> siteDataList = SiteDataMap.get(key);

            if (CollectionUtils.isEmpty(siteDataList)) {
                // 我们没有该站点
                continue;
            }

            SiteData currentSiteData = siteDataList.get(0);

            SearchVo searchVo = new SearchVo();
            BeanUtils.copyProperties(data1, searchVo);
            BeanUtils.copyProperties(currentSiteData, searchVo);
            searchVos.add(searchVo);
        }

        return searchVos;
    }

    /**
     * historical_airdata # 用以展示所有站点24小时、7天（的历史数据 # 空气清新等级-ALRVALUE、负氧离子-COL1、PM2.5-COL2、O3-COL3）。
     */
    public void historicalAirdata() {
    }

    public List<HistoricalAirdata7DayVo> historicalAirdata7Day() {

        List<HistoricalAirdata7DayVo> result = new ArrayList<>();

        // 查询所有的站点
        List<SiteData> siteData = new ArrayList<>(siteDataCache);

        // 7天之前
        DateTime dateTime = DateUtil.offsetDay(new Date(), -7);

        DataExample dataExample = new DataExample();
        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeGreaterThan(dateTime.toJdkDate());

        List<Data> data = dataMapper.selectByExample(dataExample);
        Map<String, List<Data>> dataMap =
                data.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        for (SiteData siteDatum : siteData) {

            List<Data> dataList = dataMap.get(siteDatum.getSitecode().toLowerCase());

            HistoricalAirdata7DayVo vo = buildHistoricalAirdata7Hour(siteDatum, dataList);
            result.add(vo);
        }

        return result;
    }

    /**
     * { "siteId":"3ad8f5b95f064998aad1e81520fec41e", "timeType":2,
     * "COLLECTTIME":["05-11","05-12","05-12","05-12","05-12","05-12","05-12"],
     * "ALRVALUE":[123,456,789,023,456,789,789], "COL1":[2813,123,456,789,123,456,789],
     * "COL2":[2813,123,456,789,123,456,789], "COL3":[2813,123,456,789,123,456,789] }, 构建7天的VO
     */
    public HistoricalAirdata7DayVo buildHistoricalAirdata7Hour(
            SiteData siteDatum, List<Data> dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            dataList = new ArrayList<>();
        }

        HistoricalAirdata7DayVo vo = new HistoricalAirdata7DayVo();
        vo.setSiteid(siteDatum.getSiteid());

        // 获取现在的时间
        Date now = new Date();
        String nowString = DateUtil.format(now, "MM-dd");

        // 获取7天之前的时间
        Date before7Day = DateUtil.offsetDay(now, -6).toJdkDate();
        String before7DayString = DateUtil.format(before7Day, "MM-dd");

        // 根据天分组
        Map<String, List<Data>> dayDataMap =
                dataList.stream()
                        .collect(Collectors.groupingBy(x -> DateUtil.format(x.getCollecttime(), "MM-dd")));

        while (true) {

            vo.getCollecttime().add(before7DayString);

            List<Data> data = dayDataMap.get(before7DayString);
            if (null == data) {
                data = new ArrayList<>();
            }
            List<String> col1s = data.stream().map(x -> x.getCol1()).collect(Collectors.toList());
            vo.getCol1().add(AvgUtils.getAvgFromString(col1s));

            List<String> col2s = data.stream().map(x -> x.getCol2()).collect(Collectors.toList());
            vo.getCol2().add(AvgUtils.getAvgFromString(col2s));

            List<String> col3s = data.stream().map(x -> x.getCol3()).collect(Collectors.toList());
            vo.getCol3().add(AvgUtils.getAvgFromString(col3s));

            Map<String, List<String>> airLevelsMap =
                    data.stream()
                            .map(x -> x.getAirlevelname())
                            .filter((x -> (null != x) && (!x.contains("-"))))
                            .collect(Collectors.groupingBy(x -> x));

            int size = 0;
            int airLevel = 0;
            Set<Entry<String, List<String>>> entries = airLevelsMap.entrySet();
            for (Entry<String, List<String>> entry : entries) {
                if (entry.getValue().size() > size) {
                    size = entry.getValue().size();
                    airLevel = BaseConstant.AirLevelMap.get(entry.getValue().get(0));
                }
            }
            vo.getAlrvalue().add((airLevel));

            if (nowString.equals(before7DayString)) {
                break;
            }

            // 下一天
            before7Day = DateUtil.offsetDay(before7Day, 1).toJdkDate();
            before7DayString = DateUtil.format(before7Day, "MM-dd");
        }

        return vo;
    }

    public List<HistoricalAirdata24HourVo> historicalAirdata24Hour() {

        List<HistoricalAirdata24HourVo> result = new ArrayList<>();

        // 查询所有的站点(走缓存)
        List<SiteData> siteData = new ArrayList<>(siteDataCache);

        // 24小时之前
        DateTime dateTime = DateUtil.offsetDay(new Date(), -1);

        DataExample dataExample = new DataExample();
        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeGreaterThan(dateTime.toJdkDate());

        List<Data> data = dataMapper.selectByExample(dataExample);
        Map<String, List<Data>> dataMap =
                data.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        for (SiteData siteDatum : siteData) {

            List<Data> dataList = dataMap.get(siteDatum.getSitecode().toLowerCase());

            HistoricalAirdata24HourVo historicalAirdata24HourVo =
                    buildHistoricalAirdata24HourVo(siteDatum, dataList);
            result.add(historicalAirdata24HourVo);
        }

        return result;
    }

    private HistoricalAirdata24HourVo buildHistoricalAirdata24HourVo(
            SiteData siteDatum, List<Data> dataList) {
        HistoricalAirdata24HourVo vo = new HistoricalAirdata24HourVo();

        vo.setSiteid(siteDatum.getSiteid());

        if (CollectionUtils.isEmpty(dataList)) {
            return vo;
        }

        // 排序
        dataList.sort(
                (x, y) -> {
                    long xtime = x.getCollecttime().getTime();
                    long ytime = y.getCollecttime().getTime();

                    if (xtime > ytime) {
                        return 1;
                    } else if (xtime < ytime) {
                        return -1;
                    } else {
                        return 0;
                    }
                });

        for (Data data : dataList) {
            vo.getCollecttime().add(DateUtil.format(data.getCollecttime(), "MM-dd HH"));
            vo.getCol1().add(data.getCol1());
            vo.getCol2().add(data.getCol2());
            vo.getCol3().add(data.getCol3());
            vo.getAlrvalue().add(BaseConstant.AirLevelMap.get(data.getAirlevelname()));
        }

        return vo;
    }

    // 获取站点前一日的日均值
    public List<CityLast7daysVo> cityLast7days() {

        List<CityLast7daysVo> result = new ArrayList<>();

        // 查询所有站点
        List<SiteData> siteData = new ArrayList<>(siteDataCache);

        Map<String, List<SiteData>> siteDataMap =
                siteData.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        // 今天的0点0分
        DateTime end = DateUtil.beginOfDay(new Date());
        // 昨天的O点0分
        DateTime begin = DateUtil.offsetDay(end.toJdkDate(), -1);

        DataExample dataExample = new DataExample();
        // 获取当日的最开始
        DateTime dateTime = DateUtil.beginOfDay(new Date());
        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeBetween(begin.toJdkDate(), end.toJdkDate());
        List<Data> dataOneDay = dataMapper.selectByExample(dataExample);

        Map<String, List<Data>> dataMap =
                dataOneDay.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        Set<Entry<String, List<SiteData>>> entries = siteDataMap.entrySet();

        for (Entry<String, List<SiteData>> entry : entries) {

            String key = entry.getKey();
            SiteData value = entry.getValue().get(0);

            CityLast7daysVo vo = new CityLast7daysVo();
            vo.setSiteid(value.getSiteid());
            vo.setSitename(value.getSitename());
            vo.setLatitude(value.getLatitude());
            vo.setLongitude(value.getLongitude());
            vo.setSitecode(value.getSitecode());

            List<Data> data = dataMap.get(key);
            if (null == data) {
                data = new ArrayList<>();
            }
            List<String> col1s = data.stream().map(x -> x.getCol1()).collect(Collectors.toList());
            vo.setDayAverageCOL1(AvgUtils.getAvgFromString(col1s));

            List<String> col2s = data.stream().map(x -> x.getCol2()).collect(Collectors.toList());
            vo.setDayAverageCOL2(AvgUtils.getAvgFromString(col2s));

            List<String> col3s = data.stream().map(x -> x.getCol3()).collect(Collectors.toList());
            vo.setDayAverageCOL3(AvgUtils.getAvgFromString(col3s));

            result.add(vo);
        }

        //// 计算7天的avg col1
        // 今天的0点0分
        end = DateUtil.beginOfDay(new Date());
        // 7天前的O点0分
        begin = DateUtil.offsetDay(end.toJdkDate(), -7);

        dataExample = new DataExample();
        criteria = dataExample.createCriteria();
        criteria.andCollecttimeBetween(begin.toJdkDate(), end.toJdkDate());
        List<Data> dataSevenDay = dataMapper.selectByExample(dataExample);

        dataMap =
                dataSevenDay.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        // 赋值时间
        // 赋值7天平均值
        for (CityLast7daysVo cityLast7daysVo : result) {
            // 添加时间
            cityLast7daysVo.setDayTime(
                    DateUtil.format(DateUtil.offsetDay(end.toJdkDate(), -1), "yyyy-MM-dd"));

            List<Data> data = dataMap.get(cityLast7daysVo.getSitecode().toLowerCase());
            if (data == null) {
                data = new ArrayList<>();
            }
            List<String> collect = data.stream().map(x -> x.getCol1()).collect(Collectors.toList());
            cityLast7daysVo.setSevenDaysAverageCOL1(AvgUtils.getAvgFromString(collect));
        }

        return result;
    }

    /**
     * # 获取当日站点空气数据排行和该站点当日最大的col1 # 先从站点库里，查询出所有站点的sitecode和名称 #
     * 再去空气数据库里查出，每个站点当日最新的col1及截止当前的maxcol1 # 根据col1去排序，取出前十 # 变量初始化
     */
    public List<RankingVo> ranking() {

        List<SiteData> siteData = siteDataMapper.selectByExample(new SiteDataExample());

        Map<String, List<SiteData>> siteDataMap =
                siteData.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        DataExample dataExample = new DataExample();
        // 获取当日的最开始
        DateTime dateTime = DateUtil.beginOfDay(new Date());
        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeGreaterThanOrEqualTo(dateTime.toJdkDate());
        List<Data> data = dataMapper.selectByExample(dataExample);

        // 分组
        Map<String, Double> maxCol1DataMap = new HashMap<>();
        Map<String, Double> latestCol1DataMap = new HashMap<>();
        Map<String, Date> lastupdatetimeDataMap = new HashMap<>();
        for (Data datum : data) {
            String col1 = datum.getCol1();
            String sitecode = datum.getSitecode();
            Date lastupdatetime = datum.getLastupdatetime();

            Double aDouble = maxCol1DataMap.get(sitecode);
            if (null == aDouble) {
                aDouble = -1D;
            }

            try {
                if (!col1.contains("-")) {
                    double newCol1 = Double.parseDouble(col1);
                    latestCol1DataMap.put(sitecode, newCol1);
                    aDouble = Math.max(aDouble, newCol1);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            maxCol1DataMap.put(sitecode, aDouble);


            Date date = lastupdatetimeDataMap.get(sitecode);

            if (null == date || lastupdatetime.after((date))) {
                lastupdatetimeDataMap.put(sitecode, lastupdatetime);
            }
        }

        List<RankingVo> rankingVos = new ArrayList<>();

        Set<Entry<String, List<SiteData>>> entries = siteDataMap.entrySet();
        for (Entry<String, List<SiteData>> entry : entries) {
            String key = entry.getKey();

            SiteData siteData1 = entry.getValue().get(0);

            Double aDouble = maxCol1DataMap.get(key);
            if (aDouble == null) {
                aDouble = -1D;
            }
            Double latestCol1Data = latestCol1DataMap.get(key);
            if (latestCol1Data == null) {
                latestCol1Data = -1D;
            }

            RankingVo rankingVo = new RankingVo();
            BeanUtils.copyProperties(siteData1, rankingVo);

            rankingVo.setCol1(latestCol1Data);
            rankingVo.setMaxcol1(aDouble);
            rankingVo.setLastupdatetime(lastupdatetimeDataMap.get(rankingVo.getSitecode().toLowerCase()));

            rankingVos.add(rankingVo);
        }

        // 排序
        List<RankingVo> collect = rankingVos.stream().sorted().collect(Collectors.toList());

        //        if (collect.size() > 10) {
        //            collect = collect.subList(0, 10);
        //        }

        return collect;
    }

    /**
     * 获取所有城市的空气数据（站点均值，空气质量等级众数）
     */
    public List allCity() {

        List<AllCityVo> result = new ArrayList<>();

        List<SiteData> siteData = siteDataMapper.selectByExample(new SiteDataExample());

        // 城市和数据Map
        Map<String, List<Data>> dataCache = new HashMap<>();

        // 城市和站点的关系
        Map<String, List<SiteData>> siteDataMap =
                siteData.stream().collect(Collectors.groupingBy(SiteData::getDistrict));
        Set<Entry<String, List<SiteData>>> entries = siteDataMap.entrySet();

        for (Entry<String, List<SiteData>> entry : entries) {

            String key = entry.getKey();
            List<SiteData> value = entry.getValue();

            for (SiteData cureentSiteData : value) {

                Data data = customerMapper.selectLatestNewData(cureentSiteData.getSitecode().toLowerCase());

                if (null == data) {
                    continue;
                }

                if (!dataCache.containsKey(key)) {
                    dataCache.put(key, new ArrayList<>());
                }

                dataCache.get(key).add(data);
            }
        }

        Set<Entry<String, List<Data>>> dataCacheSet = dataCache.entrySet();

        for (Entry<String, List<Data>> stringListEntry : dataCacheSet) {
            String key = stringListEntry.getKey();
            List<Data> value = stringListEntry.getValue();
            if (CollectionUtils.isEmpty(value)) {
                value = new ArrayList<>();
            }

            AllCityVo vo = new AllCityVo();
            vo.setCity(key);
            value = value.stream().sorted().collect(Collectors.toList());

            if (value.size() > 0) {
                BeanUtils.copyProperties(value.get(0), vo);
            }

            // 设置最大值
            List<String> col1s = value.stream().map(x -> x.getCol1()).collect(Collectors.toList());
            col1s.add(vo.getCol1());
            vo.setMaxcol1(MaxUtils.getMaxFromString(col1s));

            result.add(vo);
        }

        return result;
    }

    // {
    //            "AIRLEVELCODE":"Ⅰ",
    //            "AIRLEVELNAME":"很清新",
    //            "COLLECTTIME":"2020-05-04",
    //            "COL1":"当前负氧离子值",
    //            "DISTRICT":"杭州",
    //            "dayAverageCOL1":"488"
    //           }
    // 获取所有城市“日评价”数据（AIRLEVELNAME或AIRLEVELCODE取众数）
    public List<CityDayEvaluationVo> cityDayEvaluation() {

        List<SiteData> siteData = siteDataMapper.selectByExample(new SiteDataExample());

        // 站点code-站点Map
        Map<String, List<SiteData>> cityCodeSiteDataMap =
                siteData.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        DataExample dataExample = new DataExample();
        // 获取当日的上一天
        DateTime endTime = DateUtil.beginOfDay(new Date());
        DateTime startTime = DateUtil.offsetDay(endTime, -1);
        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeBetween(startTime.toJdkDate(), endTime.toJdkDate());
        List<Data> data = dataMapper.selectByExample(dataExample);

        Map<String, List<Data>> cityDataMap = new HashMap<>();
        siteData.stream().forEach(x -> cityDataMap.put(x.getDistrict(), new ArrayList<>()));

        // 省-data分组
        for (Data datum : data) {
            String sitecode = datum.getSitecode();
            List<SiteData> siteDataList = cityCodeSiteDataMap.get(sitecode);
            // 没有这个站点，跳过
            if (CollectionUtils.isEmpty(siteDataList)) {
                continue;
            }
            // 站点
            SiteData current = siteDataList.get(0);

            // 省
            String district = current.getDistrict();
            cityDataMap.get(district).add(datum);
        }

        Set<Entry<String, List<Data>>> entries = cityDataMap.entrySet();

        List<CityDayEvaluationVo> result = new ArrayList<>();
        for (Entry<String, List<Data>> entry : entries) {
            String key = entry.getKey();
            List<Data> value = entry.getValue();

            CityDayEvaluationVo vo = buildCityDayEvaluationVo(key, value);

            result.add(vo);
        }

        return result;
    }

    /**
     *
     */
    private CityDayEvaluationVo buildCityDayEvaluationVo(String city, List<Data> value) {
        CityDayEvaluationVo vo = new CityDayEvaluationVo();

        // 排除无效数据
        value =
                value.stream()
                        .filter(x -> ((null != x) && (!x.getAirlevelcode().contains("-"))))
                        .collect(Collectors.toList());

        vo.setDistrict(city);

        // 获取当日的上一天
        DateTime thisDayStart = DateUtil.beginOfDay(new Date());
        DateTime yesterDay = DateUtil.offsetDay(thisDayStart, -1);
        vo.setCollecttime(DateUtil.format(yesterDay, "yyyy-MM-dd"));

        List<String> col1s = value.stream().map(x -> x.getCol1()).collect(Collectors.toList());
        vo.setDayAverageCOL1(AvgUtils.getAvgFromString(col1s));

        // 设置空气清新等级大数
        Map<String, List<Data>> airLevelMap =
                value.stream().collect(Collectors.groupingBy(Data::getAirlevelcode));
        String airlevelcode = "--";
        String airlevelname = "--";
        int maxSize = 0;
        for (Entry<String, List<Data>> stringListEntry : airLevelMap.entrySet()) {
            String key = stringListEntry.getKey();
            List<Data> dataList = stringListEntry.getValue();

            if (CollectionUtils.isEmpty(dataList)) {
                continue;
            }

            if (dataList.size() > maxSize) {
                airlevelcode = dataList.get(0).getAirlevelcode();
                airlevelname = dataList.get(0).getAirlevelname();
                maxSize = dataList.size();
            }
        }

        vo.setAirlevelcode(airlevelcode);
        vo.setAirlevelname(airlevelname);

        return vo;
    }

    public List<CityMonthEvaluationVo> cityMonthEvaluation() {

        String redisKey =
                BaseConstant.REDIS_PERFIX
                        + "PyService.cityMonthEvaluation"
                        + DateUtil.format(new Date(), "yyyy-MM-dd");

        List<CityMonthEvaluationVo> result = new ArrayList<>();

        String s = stringRedisTemplate.opsForValue().get(redisKey);

        //    if (StringUtils.isNotBlank(s)) {
        //      result = JsonUtils.jsonToList(s, CityMonthEvaluationVo.class);
        //    }
        //    if (!CollectionUtils.isEmpty(result)) {
        //      return result;
        //    }

        List<SiteData> siteData = new ArrayList<>(siteDataCache);

        // 站点code-站点Map
        Map<String, List<SiteData>> cityCodeSiteDataMap =
                siteData.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        DataExample dataExample = new DataExample();
        // 获取当月的最开始
        DateTime startDate = DateUtil.beginOfMonth(new Date());
        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeGreaterThanOrEqualTo(startDate);
        List<Data> data = dataMapper.selectByExample(dataExample);

        Map<String, List<Data>> cityDataMap = new HashMap<>();
        siteData.stream().forEach(x -> cityDataMap.put(x.getDistrict(), new ArrayList<>()));

        // 省-data分组
        for (Data datum : data) {
            String sitecode = datum.getSitecode();
            List<SiteData> siteDataList = cityCodeSiteDataMap.get(sitecode);
            // 我们没有这个站点，跳过
            if (CollectionUtils.isEmpty(siteDataList)) {
                continue;
            }
            // 站点
            SiteData current = siteDataList.get(0);
            // 省
            String district = current.getDistrict();
            cityDataMap.get(district).add(datum);
        }

        Set<Entry<String, List<Data>>> entries = cityDataMap.entrySet();

        for (Entry<String, List<Data>> entry : entries) {

            String key = entry.getKey();
            List<Data> value = entry.getValue();

            CityMonthEvaluationVo vo = buildCityMonthEvaluationVo(key, value);

            result.add(vo);
        }

        // 设置过期时间
        stringRedisTemplate
                .opsForValue()
                .set(redisKey, JsonUtils.objectToJson(result), 24, TimeUnit.HOURS);
        return result;
    }

    private CityMonthEvaluationVo buildCityMonthEvaluationVo(String city, List<Data> dataList) {
        CityMonthEvaluationVo vo = new CityMonthEvaluationVo();

        vo.setCity(city);

        vo.setCollecttimes(DateUtil.format(new Date(), "yyyy-MM"));

        if (CollectionUtils.isEmpty(dataList)) {
            vo.setQxeffect(0.0);
            return vo;
        }

        // 总数
        double size = (double) (dataList.size());
        if (size == 0D) {
            size = 1;
        }

        int interestSize = 0;
        List<Data> interestDataList =
                dataList.stream()
                        .filter(
                                x -> {
                                    String airlevelname = x.getAirlevelname();
                                    if ("很清晰".equals(airlevelname) || "清新".equals(airlevelname)) {
                                        return true;
                                    } else {
                                        return false;
                                    }
                                })
                        .collect(Collectors.toList());

        interestSize = interestDataList.size();

        vo.setQxeffect(interestSize / size);

        return vo;
    }

    public List<CityQuarterlyDataVo> cityQuarterlyData() {

        List<CityQuarterlyDataVo> result = new ArrayList<>();

        List<SiteData> siteData = new ArrayList<>(siteDataCache);

        // 站点code-站点Map
        Map<String, List<SiteData>> cityCodeSiteDataMap =
                siteData.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        DataExample dataExample = new DataExample();
        // 获取当月的最开始
        DateTime dateTime = DateUtil.beginOfQuarter(new Date());
        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeGreaterThan(dateTime);
        List<Data> data = dataMapper.selectByExample(dataExample);

        Map<String, List<Data>> cityDataMap = new HashMap<>();

        // 省-data分组
        for (Data datum : data) {
            String sitecode = datum.getSitecode();
            List<SiteData> siteDataList = cityCodeSiteDataMap.get(sitecode);
            // 我们没有这个站点，跳过
            if (CollectionUtils.isEmpty(siteDataList)) {
                continue;
            }
            // 站点
            SiteData current = siteDataList.get(0);
            // 省
            String district = current.getDistrict();
            if (!cityDataMap.containsKey(district)) {
                cityDataMap.put(district, new ArrayList<>());
            }
            cityDataMap.get(district).add(datum);
        }

        Set<Entry<String, List<Data>>> entries = cityDataMap.entrySet();

        for (Entry<String, List<Data>> entry : entries) {

            String key = entry.getKey();
            List<Data> value = entry.getValue();
            if (CollectionUtils.isEmpty(value)) {
                value = new ArrayList<>();
            }

            CityQuarterlyDataVo vo = new CityQuarterlyDataVo();
            vo.setDistrict(key);

            List<String> collect =
                    value.parallelStream().map(x -> x.getCol1()).collect(Collectors.toList());
            vo.setQuaterAverageCOL1(AvgUtils.getAvgFromString(collect));

            result.add(vo);
        }

        return result;
    }

    public List<CityHourEvaluationVo> cityHourEvaluation() {

        List<CityHourEvaluationVo> result = new ArrayList<>();
        List<SiteData> siteData = siteDataMapper.selectByExample(new SiteDataExample());
        Map<String, List<SiteData>> siteCodeMap =
                siteData.stream().collect(Collectors.groupingBy(x -> x.getSitecode().toLowerCase()));

        DataExample dataExample = new DataExample();

        // 获取当前小时
        String currentHourStartString = DateUtil.format(new Date(), "yyyy-MM-dd hh");
        DateTime currentHourStartDate = DateUtil.parse(currentHourStartString, "yyyy-MM-dd hh");
        DateTime lastHourStartDate = DateUtil.offsetHour(currentHourStartDate, -1);

        DataExample.Criteria criteria = dataExample.createCriteria();
        criteria.andCollecttimeEqualTo(lastHourStartDate.toJdkDate());
        List<Data> dataList = dataMapper.selectByExample(dataExample);

        Map<String, List<Data>> dataMap = new HashMap<>();
        // 初始化
        siteData.stream().forEach(x -> dataMap.put(x.getDistrict(), new ArrayList<>()));

        for (Data data : dataList) {

            if (!siteCodeMap.containsKey(data.getSitecode().toLowerCase())) {
                continue;
            }

            List<SiteData> siteDataList = siteCodeMap.get(data.getSitecode().toLowerCase());
            SiteData station = siteDataList.get(0);

            // 省
            String district = station.getDistrict();

            dataMap.get(district).add(data);
        }

        Set<Entry<String, List<Data>>> entries = dataMap.entrySet();
        for (Entry<String, List<Data>> entry : entries) {
            String key = entry.getKey();
            List<Data> value = entry.getValue();

            CityHourEvaluationVo vo = buildCityHourEvaluationVo(key, value);
            result.add(vo);
        }

        return result;
    }

    private CityHourEvaluationVo buildCityHourEvaluationVo(String city, List<Data> value) {
        CityHourEvaluationVo vo = new CityHourEvaluationVo();

        // 排除无效数据
        value =
                value.stream()
                        .filter(x -> ((null != x) && (!x.getAirlevelcode().contains("-"))))
                        .collect(Collectors.toList());

        vo.setDistrict(city);
        vo.setCollecttime(DateUtil.format(new Date(), "yyyy-MM-dd hh时"));

        List<String> col1s = value.stream().map(x -> x.getCol1()).collect(Collectors.toList());
        vo.setHourAverageCOL1(AvgUtils.getAvgFromString(col1s));

        // 设置空气清新等级大数
        Map<String, List<Data>> airLevelMap =
                value.stream().collect(Collectors.groupingBy(Data::getAirlevelcode));
        String airlevelcode = "--";
        String airlevelname = "--";
        int maxSize = 0;
        for (Entry<String, List<Data>> stringListEntry : airLevelMap.entrySet()) {
            String key = stringListEntry.getKey();
            List<Data> dataList = stringListEntry.getValue();

            if (CollectionUtils.isEmpty(dataList)) {
                continue;
            }

            if (dataList.size() > maxSize) {
                airlevelcode = dataList.get(0).getAirlevelcode();
                airlevelname = dataList.get(0).getAirlevelname();
                maxSize = dataList.size();
            }
        }

        if (null != value && value.size() > 0) {
            vo.setCol1(value.get(0).getCol1());
        }

        vo.setAirlevelcode(airlevelcode);
        vo.setAirlevelname(airlevelname);

        return vo;
    }
}
